﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.IO;
using Bling.DSL;
using Bling.Util;
using Bling.Properties;
using Bling.WPF;
using linq = Microsoft.Linq.Expressions;
using Bling.D3D;
using Bling.Arrays;
using Bling.Linq;

namespace Bling.DSL {
  public partial class DoubleBl {
    public QuaternionBl Slerp(QuaternionBl From, QuaternionBl To) {
      return QuaternionBl.SlerpOp.Make(From, To, this);
    }
  }
}

namespace Bling.D3D {
  /// <summary>
  ///     Provides a rendering surface for 3-D visual content.
  /// </summary>
  public class Viewport3DBl : FrameworkElementBl<Viewport3D, Viewport3DBl> {
    public Viewport3DBl() : base(new Constant<Viewport3D>(new Viewport3D())) { }
    public Viewport3DBl(Expr<Viewport3D> Provider) : base(Provider) { }
    public Viewport3DBl(CanvasBl canvas) : base(canvas, new Viewport3D()) {}
    public static implicit operator Viewport3DBl(Expr<Viewport3D> target) { return new Viewport3DBl((target)); }
    public static implicit operator Viewport3DBl(Viewport3D target) { return (new Constant<Viewport3D>(target)); }
    static Viewport3DBl() { Register(v => v); }
    /// <summary>
    /// Configures this view port with a flat/bird eye perspective where its visual consumes its entire allocated space.
    /// </summary>
    public PointBl FlatPerspective {
      set {
        var MeshSize = value;
        this.ClipToBounds = false;
        this.IsHitTestVisible = false;
        this.EdgeMode = System.Windows.Media.EdgeMode.Aliased;
        this.BitmapScalingMode = System.Windows.Media.BitmapScalingMode.NearestNeighbor;
        this.Children.AddOne = new ModelVisual3DBl() {
          Content = new SpotLightBl() {
            Color = Colors.White,
            Position = new Point3DBl(MeshSize.X, MeshSize.Y * 0.25, 3),
            Direction = new Point3DBl(0, 0, -1),
            InnerConeAngle = 70d.ToDegrees(),
            OuterConeAngle = 100d.ToDegrees(),
          },
        };
        this.Camera = new OrthographicCameraBl() {
          Position = new Point3DBl(MeshSize.X * 0.5, MeshSize.Y * 0.5, 1.0),
          Direction = {
            Look = new Point3DBl(0, 0, -1),
            Up = new Point3DBl(0, 1, 0),
          },
          Width = MeshSize.X, PlaneDistance = { Far = 5, Near = 0.1 },
        };
      }
    }

    /// <summary>
    ///     Gets or sets a camera object that projects the 3-D contents of the System.Windows.Controls.Viewport3D to
    ///     the 2-D surface of the System.Windows.Controls.Viewport3D. This is a dependency
    ///     property.
    /// </summary>
    public CameraBl Camera {
      get { return Underlying.Property<Camera>(Viewport3D.CameraProperty); }
      set { Camera.Bind = value; }
    }
    /// <summary>
    /// Gets a collection of the System.Windows.Media.Media3D.Visual3D children of
    ///  the System.Windows.Controls.Viewport3D. This is a dependency property.
    /// </summary>
    public CollectionBl<Visual3D,Visual3DBl,Visual3DCollection> Children { get { return Underlying.Property<Visual3DCollection>(Viewport3D.ChildrenProperty); } }
  }
  public abstract class BaseModel3DBl<T, BRAND> : Brand<T, BRAND>
    where T : Model3D
    where BRAND : BaseModel3DBl<T, BRAND> {
    public BaseModel3DBl(Expr<T> Underlying) : base(Underlying) { }

    public static implicit operator Model3DBl(BaseModel3DBl<T, BRAND> mod) {
      return Model3DBl.UpCast<T>(mod.Underlying);
    }
  }
  /// <summary>
  ///     Abstract class that provides functionality for 3-D models.
  /// </summary>
  public class Model3DBl : BaseModel3DBl<Model3D, Model3DBl> {
    public Model3DBl(Expr<Model3D> Underlying) : base(Underlying) { }
    public static implicit operator Model3DBl(Expr<Model3D> target) { return new Model3DBl((target)); }
    public static implicit operator Model3DBl(Model3D target) { return (new Constant<Model3D>(target)); }
    static Model3DBl() { Register(v => v); }
    public new static Model3DBl UpCast<T>(Expr<T> value) where T : Model3D {
      return BaseModel3DBl<Model3D, Model3DBl>.UpCast<T>(value);
    }
  }
  /// <summary>
  ///     System.Windows.Media.Media3D.Model3D object that represents lighting applied
  ///     to a 3-D scene.
  /// </summary>
  public abstract class BaseLightBl<T, BRAND> : BaseModel3DBl<T, BRAND>
    where T : Light
    where BRAND : BaseLightBl<T, BRAND> {
    public BaseLightBl(Expr<T> Underlying) : base(Underlying) { }
    /// <summary>
    ///     Gets or sets the color of the light.
    /// </summary>
    public ColorBl Color {
      get { return Underlying.Property<Color>(Light.ColorProperty); }
      set { Color.Bind = value; }
    }
    public static implicit operator LightBl(BaseLightBl<T, BRAND> light) {
      return LightBl.UpCast<T>(light.Underlying);
    }
  }
  /// <summary>
  ///     System.Windows.Media.Media3D.Model3D object that represents lighting applied
  ///     to a 3-D scene.
  /// </summary>
  public class LightBl : BaseLightBl<Light, LightBl> {
    public LightBl(Expr<Light> Underlying) : base(Underlying) { }
    public static implicit operator LightBl(Expr<Light> target) { return new LightBl((target)); }
    public static implicit operator LightBl(Light target) { return (new Constant<Light>(target)); }
    static LightBl() { Register(v => v); }
    public new static LightBl UpCast<T>(Expr<T> value) where T : Light {
      return BaseLightBl<Light, LightBl>.UpCast<T>(value);
    }
  }
  /// <summary>
  ///     Light object that projects its effect along a direction specified by a System.Windows.Media.Media3D.Vector3D.
  /// </summary>
  public class DirectionalLightBl : BaseLightBl<DirectionalLight, DirectionalLightBl> {
    public DirectionalLightBl(Expr<DirectionalLight> Underlying) : base(Underlying) { }
    public DirectionalLightBl() : this(new Constant<DirectionalLight>(new DirectionalLight())) { }
    public static implicit operator DirectionalLightBl(Expr<DirectionalLight> target) { return new DirectionalLightBl((target)); }
    public static implicit operator DirectionalLightBl(DirectionalLight target) { return (new Constant<DirectionalLight>(target)); }
    static DirectionalLightBl() { Register(v => v); }
    /// <summary>
    ///     Represents the vector along which the light's effect will be seen on models
    ///     in a 3-D scene. This is a dependency property.
    ///     Vector3D along which the light projects, and which must have a non-zero magnitude.
    ///     The default value is (0,0,-1).
    /// </summary>
    public Point3DBl Direction {
      get { return Underlying.Property<Vector3D>(DirectionalLight.DirectionProperty); }
      set { Direction.Bind = value; }
    }
  }
  /// <summary>
  ///     Light object that applies light to objects uniformly, regardless of their
  ///    shape.
  /// </summary>
  public class AmbientLightBl : BaseLightBl<AmbientLight, AmbientLightBl> {
    public AmbientLightBl(Expr<AmbientLight> Underlying) : base(Underlying) { }
    public AmbientLightBl() : this(new Constant<AmbientLight>(new AmbientLight())) { }
    public static implicit operator AmbientLightBl(Expr<AmbientLight> target) { return new AmbientLightBl((target)); }
    public static implicit operator AmbientLightBl(AmbientLight target) { return (new Constant<AmbientLight>(target)); }
    static AmbientLightBl() { Register(v => v); }
  }
  public abstract class BasePointLightBl<T, BRAND> : BaseLightBl<T, BRAND>
    where T : PointLightBase
    where BRAND : BasePointLightBl<T, BRAND> {
    public BasePointLightBl(Expr<T> Underlying) : base(Underlying) { }

    public class AttenuationSet {
      internal Expr<T> Underlying;
      /// <summary>
      ///     Gets or sets a constant value by which the intensity of the light diminishes
      ///     over distance. This is a dependency property.
      /// </summary>
      public DoubleBl Constant {
        get { return Underlying.Property<double>(PointLightBase.ConstantAttenuationProperty); }
        set { Constant.Bind = value; }
      }
      /// <summary>
      ///     Gets or sets a value that specifies the linear diminution of the light's
      ///     intensity over distance. This is a dependency property.
      /// </summary>
      public DoubleBl Linear {
        get { return Underlying.Property<double>(PointLightBase.LinearAttenuationProperty); }
        set { Linear.Bind = value; }
      }
      /// <summary>
      ///     Gets or sets a value that specifies the diminution of the light's effect
      ///     over distance, calculated by a quadratic operation. This is a dependency
      ///     property.
      /// </summary>
      public DoubleBl Quadratic {
        get { return Underlying.Property<double>(PointLightBase.QuadraticAttenuationProperty); }
        set { Quadratic.Bind = value; }
      }
      internal AttenuationSet Bind {
        set {
          this.Linear = value.Linear; this.Quadratic = value.Quadratic;
          this.Constant = value.Constant;
        }
      }
      internal AttenuationSet() { }
    }
    /// <summary>
    /// Get or set values that specify the diminution of the light's effect
    /// over distance, calculated by constant, linear, and quadratic operations.
    /// likes:Attenuation = 1/constant + linear * distance + quadratic * distance * distance
    /// </summary>
    public AttenuationSet Attenuation {
      get { return new AttenuationSet() { Underlying = Underlying }; }
      set { Attenuation.Bind = (value); }
    }
    /// <summary>
    ///     Gets or sets a System.Windows.Media.Media3D.Point3D that specifies the light's
    ///     position in world space. This is a dependency property.
    /// </summary>
    public Point3DBl Position {
      get { return Underlying.Property<Point3D>(PointLightBase.PositionProperty); }
      set { Position.Bind = value; }
    }
    /// <summary>
    ///     Gets or sets the distance beyond which the light has no effect. This is a
    ///     dependency property.
    /// </summary>
    public DoubleBl Range {
      get { return Underlying.Property<double>(PointLightBase.RangeProperty); }
      set { Range.Bind = value; }
    }
  }

  /// <summary>
  ///     Represents a light source that has a specified position in space and projects
  ///     its light in all directions.
  /// </summary>
  public class PointLightBl : BasePointLightBl<PointLight, PointLightBl> {
    public PointLightBl(Expr<PointLight> Underlying) : base(Underlying) { }
    public PointLightBl() : this(new Constant<PointLight>(new PointLight())) { }
    public static implicit operator PointLightBl(Expr<PointLight> target) { return new PointLightBl((target)); }
    public static implicit operator PointLightBl(PointLight target) { return (new Constant<PointLight>(target)); }
    static PointLightBl() { Register(v => v); }
  }
  /// <summary>
  ///     Light object that projects its effect in a cone-shaped area along a specified
  ///     direction.
  /// </summary>
  public class SpotLightBl : BasePointLightBl<SpotLight, SpotLightBl> {
    public SpotLightBl(Expr<SpotLight> Underlying) : base(Underlying) { }
    public SpotLightBl() : this(new Constant<SpotLight>(new SpotLight())) { }
    public static implicit operator SpotLightBl(Expr<SpotLight> target) { return new SpotLightBl((target)); }
    public static implicit operator SpotLightBl(SpotLight target) { return (new Constant<SpotLight>(target)); }
    static SpotLightBl() { Register(v => v); }
    /// <summary>
    ///     Gets or sets a System.Windows.Media.Media3D.Vector3D that specifies the direction
    ///     in which the System.Windows.Media.Media3D.SpotLight projects its light. This
    ///     is a dependency property. The default value is 0,0,-1.
    /// </summary>
    public Point3DBl Direction {
      get { return Underlying.Property<Vector3D>(SpotLight.DirectionProperty); }
      set { Direction.Bind = value; }
    }
    /// <summary>
    ///     Gets or sets an angle that specifies the proportion of a System.Windows.Media.Media3D.SpotLight's
    ///     cone-shaped projection in which the light fully illuminates objects in the
    ///     scene. This is a dependency property. The default value is 180.
    /// </summary>
    public DegreeAngleBl InnerConeAngle {
      get { return Underlying.Property<double>(SpotLight.InnerConeAngleProperty).Bl().ToDegrees(); }
      set { InnerConeAngle.Bind = value; }
    }
    /// <summary>
    ///     Gets or sets an angle that specifies the proportion of a System.Windows.Media.Media3D.SpotLight's
    ///     cone-shaped projection outside which the light does not illuminate objects
    ///     in the scene. This is a dependency property. The default value is 90.
    /// </summary>
    public DegreeAngleBl OuterConeAngle {
      get { return Underlying.Property<double>(SpotLight.OuterConeAngleProperty).Bl().ToDegrees(); }
      set { OuterConeAngle.Bind = value; }
    }
  }
  /// <summary>
  ///     Provides services and properties common to visual 3-D objects, including
  ///     hit-testing, coordinate transformation, and bounding box calculations.
  /// </summary>
  public abstract class BaseVisual3DBl<T, BRAND> : RenderBl<T, BRAND>
    where T : Visual3D
    where BRAND : BaseVisual3DBl<T, BRAND> {
    public BaseVisual3DBl(Expr<T> Underlying) : base(Underlying) { }
    public static implicit operator Visual3DBl(BaseVisual3DBl<T, BRAND> mat) {
      if (mat is Visual3DBl) return (Visual3DBl)mat;
      else return Visual3DBl.UpCast<T>(mat.Underlying);
    }
    /// <summary>
    ///     The transformation to apply to the 3-D object. The default is the System.Windows.Media.Media3D.Transform3D.Identity
    ///     transformation.
    /// </summary>
    public Transform3DBl Transform {
      get { return Underlying.Property<Transform3D>(Visual3D.TransformProperty); }
      set { Transform.Bind = value; }
    }
  }
  /// <summary>
  ///     Provides services and properties common to visual 3-D objects, including
  ///     hit-testing, coordinate transformation, and bounding box calculations.
  /// </summary>
  public class Visual3DBl : BaseVisual3DBl<Visual3D, Visual3DBl> {
    public Visual3DBl(Expr<Visual3D> Underlying) : base(Underlying) { }
    public static implicit operator Visual3DBl(Expr<Visual3D> target) { return new Visual3DBl((target)); }
    public static implicit operator Visual3DBl(Visual3D target) { return (new Constant<Visual3D>(target)); }
    static Visual3DBl() { Register(v => v); }
    public new static Visual3DBl UpCast<T>(Expr<T> value) where T : Visual3D {
      return BaseVisual3DBl<Visual3D, Visual3DBl>.UpCast<T>(value);
    }
  }
  /// <summary>
  ///     System.Windows.Media.Visual that contains 3-D models.
  /// </summary>
  public class ModelVisual3DBl : BaseVisual3DBl<ModelVisual3D, ModelVisual3DBl> {
    public ModelVisual3DBl(Expr<ModelVisual3D> Underlying) : base(Underlying) { }
    public ModelVisual3DBl() : base(new Constant<ModelVisual3D>(new ModelVisual3D())) { }
    public static implicit operator ModelVisual3DBl(Expr<ModelVisual3D> target) { return new ModelVisual3DBl((target)); }
    public static implicit operator ModelVisual3DBl(ModelVisual3D target) { return (new Constant<ModelVisual3D>(target)); }
    static ModelVisual3DBl() { Register(v => v); }
    /// <summary>
    ///     System.Windows.Media.Media3D.Transform3D set on the model. The default value
    ///     is System.Windows.Media.Media3D.MatrixTransform3D.
    /// </summary>
    public new Transform3DBl Transform {
      get { return Underlying.Property<Transform3D>(ModelVisual3D.TransformProperty); }
      set { Transform.Bind = value; }
    }
    /// <summary>
    ///     System.Windows.Media.Media3D.Model3D that comprises the content of the System.Windows.Media.Media3D.ModelVisual3D.
    /// </summary>
    public Model3DBl Content {
      get { return Underlying.Property<Model3D>(ModelVisual3D.ContentProperty); }
      set { Content.Bind = value; }
    }
  }
  /// <summary>
  ///     Renders the 2-D children within the specified 3-D viewport bounds.
  /// </summary>
  public class Viewport2DVisual3DBl : BaseVisual3DBl<Viewport2DVisual3D, Viewport2DVisual3DBl> {
    public Viewport2DVisual3DBl(Expr<Viewport2DVisual3D> Underlying) : base(Underlying) { }
    public Viewport2DVisual3DBl() : base(new Constant<Viewport2DVisual3D>(new Viewport2DVisual3D())) { }
    public static implicit operator Viewport2DVisual3DBl(Expr<Viewport2DVisual3D> target) { return new Viewport2DVisual3DBl((target)); }
    public static implicit operator Viewport2DVisual3DBl(Viewport2DVisual3D target) { return (new Constant<Viewport2DVisual3D>(target)); }
    static Viewport2DVisual3DBl() { Register(v => v); }
    /// <summary>
    ///     The 3-D geometry for this System.Windows.Media.Media3D.Viewport2DVisual3D.
    /// </summary>
    public Geometry3DBl Geometry { get { return Underlying.Property<Geometry3D>(Viewport2DVisual3D.GeometryProperty); } set { Geometry.Bind = value; } }
    /// <summary>
    ///     The material for the 3-D object.
    /// </summary>
    public MaterialBl Material { get { return Underlying.Property<Material>(Viewport2DVisual3D.MaterialProperty); } set { Material.Bind = value; } }
    /// <summary>
    ///     The visual to be placed on the 3-D object.
    /// </summary>
    public VisualBl Visual { get { return Underlying.Property<Visual>(Viewport2DVisual3D.VisualProperty); } set { Visual.Bind = value; } }
  }

  /// <summary>
  ///     Abstract base class for materials.
  /// </summary>
  public abstract class BaseMaterialBl<T, BRAND> : Brand<T, BRAND>
    where T : Material
    where BRAND : BaseMaterialBl<T, BRAND> {
    public BaseMaterialBl(Expr<T> Underlying) : base(Underlying) { }
    public static implicit operator MaterialBl(BaseMaterialBl<T, BRAND> mat) {
      if (mat is MaterialBl) return (MaterialBl)mat;
      else return MaterialBl.UpCast<T>(mat.Underlying);
    }
    /// <summary>
    /// XXX: no documentation found.
    /// </summary>
    public BoolBl IsVisualHostMaterial {
      get { return Underlying.Property<bool>(Viewport2DVisual3D.IsVisualHostMaterialProperty); }
      set { IsVisualHostMaterial.Bind = value; }
    }
  }
  /// <summary>
  ///     Abstract base class for materials.
  /// </summary>
  public class MaterialBl : BaseMaterialBl<Material, MaterialBl> {
    public MaterialBl(Expr<Material> Underlying) : base(Underlying) { }
    public static implicit operator MaterialBl(Expr<Material> target) { return new MaterialBl((target)); }
    public static implicit operator MaterialBl(Material target) { return (new Constant<Material>(target)); }
    static MaterialBl() { Register(v => v); }
    public new static MaterialBl UpCast<T>(Expr<T> value) where T : Material {
      return BaseMaterialBl<Material, MaterialBl>.UpCast<T>(value);
    }
  }
  /// <summary>
  ///     Allows the application of a 2-D brush, like a System.Windows.Media.SolidColorBrush
  ///     or System.Windows.Media.TileBrush, to a diffusely-lit 3-D model.
  /// </summary>
  public class DiffuseMaterialBl : BaseMaterialBl<DiffuseMaterial, DiffuseMaterialBl> {
    public DiffuseMaterialBl(Expr<DiffuseMaterial> Underlying) : base(Underlying) { }
    public DiffuseMaterialBl() : this(new Constant<DiffuseMaterial>(new DiffuseMaterial())) { }
    public static implicit operator DiffuseMaterialBl(Expr<DiffuseMaterial> target) { return new DiffuseMaterialBl((target)); }
    public static implicit operator DiffuseMaterialBl(DiffuseMaterial target) { return (new Constant<DiffuseMaterial>(target)); }
    static DiffuseMaterialBl() { Register(v => v); }
    /// <summary>
    ///     The color allowed to emit from the System.Windows.Media.Media3D.Material.
    ///     The default value is #FFFFFF. Since all colors make up white, all colors
    ///     are visible by default.
    /// </summary>
    public ColorBl Color { get { return Underlying.Property<Color>(DiffuseMaterial.ColorProperty); } set { Color.Bind = value; } }
    /// <summary>
    ///     System.Windows.Media.Brush to be applied as a System.Windows.Media.Media3D.Material
    ///     to a 3-D model. This is a dependency property.
    /// </summary>
    public BrushBl Brush { get { return Underlying.Property<Brush>(DiffuseMaterial.BrushProperty); } set { Brush.Bind = value; } }
    /// <summary>
    ///     The color of the ambient light emitted by the 3D object. The default value
    ///     is #FFFFFF.
    /// </summary>
    public ColorBl AmbientColor { get { return Underlying.Property<Color>(DiffuseMaterial.AmbientColorProperty); } set { AmbientColor.Bind = value; } }
  }
  /// <summary>
  ///     Allows a 2-D brush, like a System.Windows.Media.SolidColorBrush or System.Windows.Media.TileBrush,
  ///     to be applied to a specularly-lit 3-D model.
  /// </summary>
  public class SpecularMaterialBl : BaseMaterialBl<SpecularMaterial, SpecularMaterialBl> {
    public SpecularMaterialBl(Expr<SpecularMaterial> Underlying) : base(Underlying) { }
    public SpecularMaterialBl() : this(new Constant<SpecularMaterial>(new SpecularMaterial())) { }
    public static implicit operator SpecularMaterialBl(Expr<SpecularMaterial> target) { return new SpecularMaterialBl((target)); }
    public static implicit operator SpecularMaterialBl(SpecularMaterial target) { return (new Constant<SpecularMaterial>(target)); }
    static SpecularMaterialBl() { Register(v => v); }
    /// <summary>
    ///     Gets or sets a value that filters the color properties of the material applied
    ///     to the model. This is a dependency property.
    /// </summary>
    public ColorBl Color { get { return Underlying.Property<Color>( SpecularMaterial.ColorProperty); } set { Color.Bind = value; } }
    /// <summary>
    ///     Gets or sets the 2-D brush to apply to a specularly-lit 3-D model. This is
    ///     a dependency property.
    /// </summary>
    public BrushBl Brush { get { return Underlying.Property<Brush>(SpecularMaterial.BrushProperty); } set { Brush.Bind = value; } }
    /// <summary>
    ///     Relative contribution, for a material applied as a 2-D brush to a 3-D model,
    ///     of the specular component of the lighting model.
    /// </summary>
    public DoubleBl SpecularPower { get { return Underlying.Property<double>(SpecularMaterial.SpecularPowerProperty); } set { SpecularPower.Bind = value; } }
  }
  /// <summary>
  ///     Applies a System.Windows.Media.Brush to a 3-D model so that it participates
  ///     in lighting calculations as if the System.Windows.Media.Media3D.Material
  ///     were emitting light equal to the color of the System.Windows.Media.Brush.
  /// </summary>
  public class EmissiveMaterialBl : BaseMaterialBl<EmissiveMaterial, EmissiveMaterialBl> {
    public EmissiveMaterialBl(Expr<EmissiveMaterial> Underlying) : base(Underlying) { }
    public EmissiveMaterialBl() : this(new Constant<EmissiveMaterial>(new EmissiveMaterial())) { }
    public static implicit operator EmissiveMaterialBl(Expr<EmissiveMaterial> target) { return new EmissiveMaterialBl((target)); }
    public static implicit operator EmissiveMaterialBl(EmissiveMaterial target) { return (new Constant<EmissiveMaterial>(target)); }
    static EmissiveMaterialBl() { Register(v => v); }
    /// <summary>
    ///     The color of the light.
    /// </summary>
    public ColorBl Color { get { return Underlying.Property<Color>(EmissiveMaterial.ColorProperty); } set { Color.Bind = value; } }
    /// <summary>
    ///     The brush applied by the System.Windows.Media.Media3D.EmissiveMaterial. The
    ///     default value is null.
    /// </summary>
    public BrushBl Brush { get { return Underlying.Property<Brush>(EmissiveMaterial.BrushProperty); } set { Brush.Bind = value; } }
  }
  /// <summary>
  ///     Classes that derive from this abstract base class define 3D geometric shapes.
  ///     The System.Windows.Media.Media3D.Geometry3D class of objects can be used
  ///     for hit-testing and rendering 3D graphic data.
  /// </summary>
  public abstract class BaseGeometry3DBl<T, BRAND> : Brand<T, BRAND>
    where T : Geometry3D
    where BRAND : BaseGeometry3DBl<T, BRAND> {
    public BaseGeometry3DBl(Expr<T> Underlying) : base(Underlying) { }
    public static implicit operator Geometry3DBl(BaseGeometry3DBl<T, BRAND> geom) {
      if (geom is Geometry3DBl) return (Geometry3DBl)geom;
      else return Geometry3DBl.UpCast<T>(geom.Underlying);
    }
  }
  /// <summary>
  ///     Classes that derive from this abstract base class define 3D geometric shapes.
  ///     The System.Windows.Media.Media3D.Geometry3D class of objects can be used
  ///     for hit-testing and rendering 3D graphic data.
  /// </summary>
  public class Geometry3DBl : BaseGeometry3DBl<Geometry3D, Geometry3DBl> {
    public Geometry3DBl(Expr<Geometry3D> Underlying) : base(Underlying) { }
    public static implicit operator Geometry3DBl(Expr<Geometry3D> target) { return new Geometry3DBl((target)); }
    public static implicit operator Geometry3DBl(Geometry3D target) { return (new Constant<Geometry3D>(target)); }
    static Geometry3DBl() { Register(v => v); }
    public new static Geometry3DBl UpCast<T>(Expr<T> value) where T : Geometry3D {
      return BaseGeometry3DBl<Geometry3D, Geometry3DBl>.UpCast<T>(value);
    }
  }
  /// <summary>
  ///     Triangle primitive for building a 3-D shape.
  /// </summary>
  public class MeshGeometry3DBl : BaseGeometry3DBl<MeshGeometry3D, MeshGeometry3DBl> {
    public MeshGeometry3DBl(Expr<MeshGeometry3D> Underlying) : base(Underlying) { }
    public MeshGeometry3DBl() : this(new Constant<MeshGeometry3D>(new MeshGeometry3D())) { }
    public static implicit operator MeshGeometry3DBl(Expr<MeshGeometry3D> target) { return new MeshGeometry3DBl((target)); }
    public static implicit operator MeshGeometry3DBl(MeshGeometry3D target) { return (new Constant<MeshGeometry3D>(target)); }
    static MeshGeometry3DBl() { Register(v => v); }
    /// <summary>
    ///     Gets or sets a collection of vertex positions for a System.Windows.Media.Media3D.MeshGeometry3D.
    ///     This is a dependency property.
    /// </summary>
    public Point3DCollectionBl Positions { 
      get { return Underlying.Property<Point3DCollection>(MeshGeometry3D.PositionsProperty); } 
      set { Positions.Bind = value; } 
    }
    /// <summary>
    ///     Gets or sets a collection of texture coordinates for the System.Windows.Media.Media3D.MeshGeometry3D.
    ///     This is a dependency property.
    /// </summary>
    public PointCollectionBl TextureCoordinates {
      get { return Underlying.Property<PointCollection>(MeshGeometry3D.TextureCoordinatesProperty); }
      set { TextureCoordinates.Bind = value; }
    }
    /// <summary>
    ///     Collection that contains the triangle indices of the MeshGeometry3D.
    /// </summary>
    public IntCollectionBl TriangleIndices {
      get { return Underlying.Property<Int32Collection>(MeshGeometry3D.TriangleIndicesProperty); }
      set { TriangleIndices.Bind = value; }
    }
    /// <summary>
    ///     Gets or sets a collection of normal vectors for the System.Windows.Media.Media3D.MeshGeometry3D.
    ///     This is a dependency property.
    /// </summary>
    public Vector3DCollectionBl Normals {
      get { return Underlying.Property<Vector3DCollection>(MeshGeometry3D.NormalsProperty); }
      set { Normals.Bind = value; }
    }
  }
  /// <summary>
  /// Associate a mesh with a number of rows and columns, will set all mesh properties accordingly. 
  /// </summary>
  public class GridMesh {
    private readonly MeshGeometry3DBl Mesh;
    /// <summary>
    /// Create a grid mesh with exisiting mesh geometry and specified column and row counts.
    /// </summary>
    /// <param name="Mesh">Existing mesh to manage.</param>
    /// <param name="ColumnCount">Number of columns in mesh.</param>
    /// <param name="RowCount">Number of rows in Mesh.</param>
    public GridMesh(MeshGeometry3DBl Mesh, int ColumnCount, int RowCount) : base() {
      this.Mesh = Mesh;
      this.ColumnCount = ColumnCount;
      this.RowCount = RowCount;
      Init();
    }
    public static implicit operator Geometry3DBl(GridMesh m) { return m.Mesh; }
    /// <summary>
    /// Create a grid mesh with a new mesh geometry and specified column and row counts.
    /// </summary>
    /// <param name="ColumnCount">Number of columns in mesh.</param>
    /// <param name="RowCount">Number of rows in Mesh.</param>
    public GridMesh(int ColumnCount, int RowCount) : this(new MeshGeometry3DBl(), ColumnCount, RowCount) { }
    /// <summary>
    /// Number of columns in mesh.
    /// </summary>
    public readonly int ColumnCount;
    /// <summary>
    /// Number of rows in mesh.
    /// </summary>
    public readonly int RowCount;
    /// <summary>
    /// Create an action that refreshes mesh geometry based on a 2D array of 3D points values.
    /// </summary>
    /// <param name="values">2D array of 3D points, column and row counts must be the same as the grid mesh.</param>
    /// <returns></returns>
    public Action Refresh(Array2D<Point3D> values) {
      (values.ColumnCount == ColumnCount && values.RowCount == RowCount).Assert();
      var values0 = values.Vertical1D;
      return Mesh.Positions.RefreshAction(i => values0[i], ColumnCount * RowCount);
    }
    private void Init() {
      (ColumnCount > 1 && RowCount > 1).Assert();
      DoubleBl dx = 100d / ((double)(ColumnCount - 1));
      DoubleBl dy = 100d / ((double)(RowCount - 1));
      List<Point3DBl> Positions = new List<Point3DBl>();
      List<IntBl> TriangleIndices = new List<IntBl>();
      List<PointBl> TextureCoord = new List<PointBl>();
      DoubleBl xp = 0;
      double xn = ColumnCount - 1d;
      double yn = RowCount - 1d;
      for (double x = 0; x < ColumnCount; x++) {
        DoubleBl yp = 0;
        for (double y = 0; y < RowCount; y++) {
          Positions.Add(new Point3DBl(xp, yp, 0));
          TextureCoord.Add(new PointBl(x / xn, 1.0 - y / yn));
          yp += dy;
        }
        xp += dx;
      }
      for (int x = 0; x < ColumnCount - 1; x++) {
        for (int y = 0; y < RowCount - 1; y++) {
          if ((x + y) % 2 == 1) {
            TriangleIndices.Add(y + (x * RowCount));
            TriangleIndices.Add((y) + ((x + 1) * RowCount));
            TriangleIndices.Add((y + 1) + x * RowCount);

            TriangleIndices.Add(y + ((x + 1) * RowCount));
            TriangleIndices.Add((y + 1) + ((x + 1) * RowCount));
            TriangleIndices.Add((y + 1) + ((x) * RowCount));
          } else {
            TriangleIndices.Add(y + (x * RowCount));
            TriangleIndices.Add((y + 1) + ((x + 1) * RowCount));
            TriangleIndices.Add((y + 1) + x * RowCount);

            TriangleIndices.Add(y + (x * RowCount));
            TriangleIndices.Add(y + ((x + 1) * RowCount));
            TriangleIndices.Add((y + 1) + ((x + 1) * RowCount));
          }
        }
      }
      Mesh.Positions         .InitElements(Positions);
      Mesh.TextureCoordinates.InitElements(TextureCoord);
      Mesh.TriangleIndices   .InitElements(TriangleIndices);
    }
  }

 
  /// <summary>
  ///     Represents an imaginary viewing position and direction in 3-D coordinate
  ///     space that describes how a 3-D model is projected onto a 2-D visual.
  /// </summary>
  public abstract class BaseCameraBl<T, BRAND> : Brand<T, BRAND>
    where T : Camera
    where BRAND : BaseCameraBl<T, BRAND> {
    public BaseCameraBl(Expr<T> Underlying) : base(Underlying) { }

    /// <summary>
    ///     Gets or sets the Transform3D applied to the camera. This is a dependency
    ///     property.
    /// </summary>
    public Transform3DBl Transform {
      get { return Underlying.Property<Transform3D>(Camera.TransformProperty); }
      set { Transform.Bind = value; }
    }
    public static implicit operator CameraBl(BaseCameraBl<T,BRAND> camera) {
      if (camera is CameraBl) return (CameraBl)camera;
      else return CameraBl.UpCast<T>(camera.Underlying);
    }
  }
  /// <summary>
  ///     Represents an imaginary viewing position and direction in 3-D coordinate
  ///     space that describes how a 3-D model is projected onto a 2-D visual.
  /// </summary>
  public class CameraBl : BaseCameraBl<Camera, CameraBl> {
    public CameraBl(Expr<Camera> Underlying) : base(Underlying) { }
    public static implicit operator CameraBl(Expr<Camera> target) { return new CameraBl((target)); }
    public static implicit operator CameraBl(Camera target) { return (new Constant<Camera>(target)); }
    static CameraBl() { Register(v => v); }
    public new static CameraBl UpCast<T>(Expr<T> value) where T : Camera {
      return BaseCameraBl<Camera, CameraBl>.UpCast<T>(value);
    }
  }
  /// <summary>
  ///     An abstract base class for perspective and orthographic projection cameras.
  /// </summary>
  public abstract class BaseProjectionCameraBl<T, BRAND> : BaseCameraBl<T, BRAND>
    where T : ProjectionCamera
    where BRAND : BaseProjectionCameraBl<T, BRAND> {
    public BaseProjectionCameraBl(Expr<T> Underlying) : base(Underlying) { }

    public class PlaneDistanceSet {
      internal Expr<T> Underlying;
      /// <summary>
      ///     Gets or sets a value that specifies the distance from the camera of the camera's
      ///     far clip plane. This is a dependency property.
      /// </summary>
      public DoubleBl Far {
        get { return Underlying.Property<double>(ProjectionCamera.FarPlaneDistanceProperty); }
        set { Far.Bind = value; }
      }
      /// <summary>
      ///     Gets or sets a value that specifies the distance from the camera of the camera's
      ///     near clip plane. This is a dependency property.
      /// </summary>
      public DoubleBl Near {
        get { return Underlying.Property<double>(ProjectionCamera.NearPlaneDistanceProperty); }
        set { Near.Bind = value; }
      }
      internal void Bind(PlaneDistanceSet set) {
        Far.Bind = set.Far; Near.Bind = set.Near;
      }
    }
    /// <summary>
    ///     Gets or sets values that specify the distance from the camera of the camera's
    ///     far and near clip planes. This is a dependency property.
    /// </summary>
    public PlaneDistanceSet PlaneDistance {
      get { return new PlaneDistanceSet() { Underlying = Underlying }; }
      set { PlaneDistance.Bind(value); }
    }
    public class DirectionSet {
      internal Expr<T> Underlying;
      /// <summary>
      ///     Gets or sets a System.Windows.Media.Media3D.Vector3D which defines the direction
      ///     in which the camera is looking in world coordinates. This is a dependency
      ///     property.
      /// </summary>
      public Point3DBl Look {
        get { return Underlying.Property<Vector3D>(ProjectionCamera.LookDirectionProperty); }
        set { Look.Bind = value; }
      }
      /// <summary>
      ///     Gets or sets a System.Windows.Media.Media3D.Vector3D which defines the upward
      ///     direction of the camera. This is a dependency property.
      /// </summary>
      public Point3DBl Up {
        get { return Underlying.Property<Vector3D>(ProjectionCamera.UpDirectionProperty); }
        set { Up.Bind = value; }
      }
      internal void Bind(DirectionSet set) {
        Look.Bind = set.Look; Up.Bind = set.Up;
      }
    }
    /// <summary>
    ///     Get or set points that define the look and upward
    ///     directions of the camera.
    /// </summary>
    public DirectionSet Direction {
      get { return new DirectionSet() { Underlying = Underlying }; }
      set { Direction.Bind(value); }
    }
    /// <summary>
    ///     Gets or sets the position of the camera in world coordinates. This is a dependency
    ///     property.
    /// </summary>
    public Point3DBl Position {
      get { return Underlying.Property<Point3D>(ProjectionCamera.PositionProperty); }
      set { Position.Bind = value; }
    }
  }
  /// <summary>
  ///     Represents a perspective projection camera.
  /// </summary>
  public class PerspectiveCameraBl : BaseProjectionCameraBl<PerspectiveCamera, PerspectiveCameraBl> {
    public PerspectiveCameraBl(Expr<PerspectiveCamera> Underlying) : base(Underlying) { }
    public PerspectiveCameraBl() : this(new Constant<PerspectiveCamera>(new PerspectiveCamera())) { }
    public static implicit operator PerspectiveCameraBl(Expr<PerspectiveCamera> target) { return new PerspectiveCameraBl((target)); }
    public static implicit operator PerspectiveCameraBl(PerspectiveCamera target) { return (new Constant<PerspectiveCamera>(target)); }
    static PerspectiveCameraBl() { Register(v => v); }
    /// <summary>
    ///     The camera's horizontal field of view, in degrees. The default value is 45.
    /// </summary>
    public DegreeAngleBl FieldOfView {
      get { return Underlying.Property<double>(PerspectiveCamera.FieldOfViewProperty).Bl().ToDegrees(); }
      set { FieldOfView.Bind = value; }
    }
    // XXX: doesn't work yet.
    public PointBl Size2D {
      set {
        var fovInRadians = FieldOfView.ToSimpleRadians();
        var zValue = value.X / (fovInRadians / 2).Tan / 2;
        Point3DBl negativeZAxis = new Vector3D(0, 0, -1);
        Point3DBl positiveYAxis = new Vector3D(0, 1, 0);
        Point3DBl cameraPosition = new Point3DBl(value.X / 2, value.Y / 2, zValue);
        this.Position = cameraPosition;
        this.Direction.Look = negativeZAxis;
        this.Direction.Up = positiveYAxis;
      }
    }

    /*
    public static explicit operator PerspectiveCameraBl(CameraBl camera) {
      return camera.Underlying.Coerce<PerspectiveCamera>(c => (PerspectiveCamera)c);
    }*/
  }
  /// <summary>
  ///     Represents an orthographic projection camera.
  /// </summary>
  public class OrthographicCameraBl : BaseProjectionCameraBl<OrthographicCamera, OrthographicCameraBl> {
    public OrthographicCameraBl(Expr<OrthographicCamera> Underlying) : base(Underlying) { }
    public OrthographicCameraBl() : this(new Constant<OrthographicCamera>(new OrthographicCamera())) { }
    public static implicit operator OrthographicCameraBl(Expr<OrthographicCamera> target) { return new OrthographicCameraBl((target)); }
    public static implicit operator OrthographicCameraBl(OrthographicCamera target) { return (new Constant<OrthographicCamera>(target)); }
    static OrthographicCameraBl() { Register(v => v); }
    /// <summary>
    ///     Width of the camera's viewing box, in world units.
    /// </summary>
    public DoubleBl Width {
      get { return Underlying.Property<double>(OrthographicCamera.WidthProperty); }
      set { Width.Bind = value; }
    }
  }
  /// <summary>
  ///     Provides a parent class for all three-dimensional transformations, including
  ///     translation, rotation, and scale transformations.
  /// </summary>
  public partial class Transform3DBl : Brand<Transform3D, Transform3DBl> {
    public Transform3DBl(Expr<Transform3D> v) : base(v) { }
    static Transform3DBl() { Register(v => v); }
    public static implicit operator Transform3DBl(Expr<Transform3D> v) { return new Transform3DBl(v); }
    public static implicit operator Transform3DBl(Transform3D t) { return new Constant<Transform3D>(t); }

    public Point3DBl Transform(Point3DBl p) {
      return Underlying.Combine<Point3D, Point3D>(p, (t, q) => t.Transform(q));
    }
    public Point4DBl Transform(Point4DBl p) {
      return Underlying.Combine<Point4D, Point4D>(p, (t, q) => t.Transform(q));
    }
    /// <summary>
    ///     Gets a value that specifies whether the matrix is affine.
    /// </summary>
    public BoolBl IsAffine {
      get { return Underlying.Map<bool>(t => t.IsAffine); }
    }
    /// <summary>
    /// The inverse of this matrix. 
    /// </summary>
    public Transform3DBl Inverse {
      get {
        return Underlying.Map<Transform3D>(t => (Transform3D)t.Inverse, t => (Transform3D)t.Inverse);
      }
    }
    public Point3DBl CenterSize = new Point3DBl(0, 0, 0);

    /// <summary>
    /// Set the center point of the scale/skew/rotate transform .
    /// </summary>
    /// <param name="c">Center point of rotation.</param>
    /// <returns>Itself.</returns>
    public Transform3DBl this[Point3DBl c] {
      get {
        this.CenterSize = c;
        return this;
      }
    }
    private TRANSFORM Transform<TRANSFORM>() where TRANSFORM : Transform3D, new() {
      TRANSFORM transform;
      if (Underlying.HasCurrentValue) {
        var current = (Transform3D)this.CurrentValue;
        if (current is TRANSFORM) transform = (TRANSFORM)current;
        else if (current is Transform3DGroup) {
          var group = (Transform3DGroup)current;
          transform = null;
          foreach (var v in group.Children) {
            if (v is TRANSFORM) transform = (TRANSFORM)v;
          }
          if (transform == null) {
            transform = new TRANSFORM();
            group.Children.Add(transform);
          }
        } else if (current == null) {
          transform = new TRANSFORM();
          this.Now = (transform);
        } else {
          var group = new Transform3DGroup();
          group.Children.Add(current);
          transform = new TRANSFORM();
          group.Children.Add(transform);
          this.Now = (group);
        }
      } else {
        throw new NotSupportedException();
      }
      return transform;
    }
    /// <summary>
    ///     Specifies a rotation transformation.
    /// </summary>
    public Rotation3DBl Rotate {
      get {
        var rotate = Transform<RotateTransform3D>();
        var px = rotate.Bl<double>(RotateTransform3D.CenterXProperty).Bl();
        var py = rotate.Bl<double>(RotateTransform3D.CenterYProperty).Bl();
        var pz = rotate.Bl<double>(RotateTransform3D.CenterZProperty).Bl();
        (new Point3DBl(px, py, pz)).Bind = CenterSize;
        Rotation3DBl rotateX = rotate.Bl<Rotation3D>(RotateTransform3D.RotationProperty);
        return rotateX;
      }
      set {
        Rotate.Bind = value;
      }
    }
    /// <summary>
    ///     Scales an object in the three-dimensional x-y-z plane, starting from a defined
    ///     center point. Scale factors are defined in x-, y-, and z- directions from
    ///     this center point.
    /// </summary>
    public Point3DBl Scale {
      get {
        var scale = Transform<ScaleTransform3D>();
        var px = scale.Bl<double>(ScaleTransform3D.CenterXProperty).Bl();
        var py = scale.Bl<double>(ScaleTransform3D.CenterYProperty).Bl();
        var pz = scale.Bl<double>(ScaleTransform3D.CenterZProperty).Bl();
        (new Point3DBl(px, py, pz)).Bind = CenterSize;
        var qx = scale.Bl<double>(ScaleTransform3D.ScaleXProperty).Bl();
        var qy = scale.Bl<double>(ScaleTransform3D.ScaleYProperty).Bl();
        var qz = scale.Bl<double>(ScaleTransform3D.ScaleZProperty).Bl();
        return new Point3DBl(qx, qy, qz);
      }
      set { Scale.Bind = value; }
    }
    /// <summary>
    ///     Translates an object in the three-dimensional x-y-z plane.
    /// </summary>
    public Point3DBl Translate {
      get {
        var translate = Transform<TranslateTransform3D>();
        var qx = translate.Bl<double>(TranslateTransform3D.OffsetXProperty).Bl();
        var qy = translate.Bl<double>(TranslateTransform3D.OffsetYProperty).Bl();
        var qz = translate.Bl<double>(TranslateTransform3D.OffsetZProperty).Bl();
        return new Point3DBl(qx, qy, qz);
      }
      set { Translate.Bind = value; }
    }
  }



  public class QuaternionArity : ArityInfo<Quaternion, QuaternionArity> {
    public override int Arity {
      get { return 4; }
    }
    public override Quaternion ToT(double[] values) {
      return new Quaternion(values[0], values[1], values[2], values[3]);
    }
    public override string[] AccessorNames {
      get { return new string[] { "X", "Y", "Z", "W", }; }
    }

    public override double[] ToArray(Quaternion t) {
      return new double[] { t.X, t.Y, t.Z, t.W };
    }
    public override Expr<double> Access(Expr<Quaternion> value, int idx) {
      return value.Bl()[idx];
    }
  }
  /// <summary>
  ///     Structure that represents a rotation in three dimensions.
  /// </summary>
  public class QuaternionBl : PointBl<Quaternion, QuaternionBl, QuaternionArity> {
    public QuaternionBl(Expr<Quaternion> v) : base(v) { }
    public QuaternionBl(Point3DBl point, DegreeAngleBl angle) : this(MakeOp.Make(point, angle)) {}

    private static readonly Operator<Point3D, double, Quaternion> MakeOp = new Operator<Point3D, double, Quaternion>(new OperatorMarker("Quanternion") {
      Binary = (p, a) => "new Quaternion((Vector3D)" + p + ", " + a + ")",
    }) {
      Apply = (p,a) => new Quaternion((Vector3D) p, a),
      Linq = (p,a) => linq.Expression.New(
        typeof(Quaternion).GetConstructor(new Type[] { typeof(Vector3D), typeof(double) }), 
        linq.Expression.Call(Expr<Point3D>.ExplicitConvertOperator<Vector3D>.GetF(), p), a
      ),
    };
    public override PointBl XY {
      get {
        throw new NotImplementedException();
      }
      set {
        throw new NotImplementedException();
      }
    }

    public static implicit operator QuaternionBl(Expr<Quaternion> v) { return new QuaternionBl(v); }
    public static implicit operator QuaternionBl(Quaternion v) { return new Constant<Quaternion>(v); }

    private static readonly Operator<Quaternion, double> AngleOp = new Operator<Quaternion, double>(new Markers.UnaryAccessOperator("Angle")) {
      Apply = (q) => q.Angle,
      Linq = (q) => linq.Expression.Property(q, "Angle"),
    };
    private static readonly Operator<Quaternion, Point3D> AxisOp = new Operator<Quaternion, Point3D>(new Markers.UnaryAccessOperator("Axis")) {
      Apply = (q) => (Point3D) q.Axis,
      Linq = (q) => 
        linq.Expression.Call(Expr<Vector3D>.ExplicitConvertOperator<Point3D>.GetF(), 
                             linq.Expression.Property(q, "Axis")),
    };
    private static readonly Operator<Quaternion, bool> IsIdentityOp = new Operator<Quaternion, bool>(new Markers.UnaryAccessOperator("IsIdentity")) {
      Apply = (q) => q.IsIdentity,
      Linq = (q) => linq.Expression.Property(q, "IsIdentity"),
    };
    private static readonly Operator<Quaternion, bool> IsNormalizedOp = new Operator<Quaternion, bool>(new Markers.UnaryAccessOperator("IsNormalized")) {
      Apply = (q) => q.IsNormalized,
      Linq = (q) => linq.Expression.Property(q, "IsNormalized"),
    };
    internal static readonly Operator<Quaternion, Quaternion, double, Quaternion> SlerpOp = new Operator<Quaternion, Quaternion, double, Quaternion>(new OperatorMarker("Slerp(") { 
     Cont = OperatorMarker.Container.None,
    }) {
      Apply = (q0, q1, t) => Quaternion.Slerp(q0, q1, t),
      Linq = (q0,q1,t) => linq.Expression.Call(typeof(Quaternion), "Slerp", new Type[] {}, q0, q1, t), 
    };
    private static readonly Operator<Quaternion, Quaternion> InvertOp = new Operator<Quaternion, Quaternion>(new Markers.UnaryAccessOperator("Invert")) {
      Apply = (q) => { q.Invert(); return q; },
      Linq = (q) => {
        var temp = linq.Expression.Parameter(typeof(Quaternion), "temp");
        var assign = linq.Expression.Assign(temp, q);
        var call = linq.Expression.Call(assign, "Invert", new Type[] {});
        return linq.Expression.Block(typeof(Quaternion), new linq.ParameterExpression[] { temp }, assign, call, temp);
      }
    };
    /// <summary>
    /// Return this quaternion's inverse.
    /// </summary>
    public QuaternionBl Invert { get { return InvertOp.Make(this); } }

    private static readonly Operator<Quaternion, Quaternion> NormalizeOp = new Operator<Quaternion, Quaternion>(new Markers.UnaryAccessOperator("Normalize")) {
      Apply = (q) => { q.Normalize(); return q; },
      Linq = (q) => {
        var temp = linq.Expression.Parameter(typeof(Quaternion), "temp");
        var assign = linq.Expression.Assign(temp, q);
        var call = linq.Expression.Call(assign, "Normalize", new Type[] { });
        return linq.Expression.Block(typeof(Quaternion), new linq.ParameterExpression[] { temp }, assign, call, temp);
      }
    };
    /// <summary>
    /// Return this quaternion's normal.
    /// </summary>
    public QuaternionBl Normalize { get { return NormalizeOp.Make(this); } }
    private static readonly Operator<Quaternion, Quaternion> ConjugateOp = new Operator<Quaternion, Quaternion>(new Markers.UnaryAccessOperator("Conjugate")) {
      Apply = (q) => { q.Conjugate(); return q; },
      Linq = (q) => {
        var temp = linq.Expression.Parameter(typeof(Quaternion), "temp");
        var assign = linq.Expression.Assign(temp, q);
        var call = linq.Expression.Call(assign, "Conjugate", new Type[] { });
        return linq.Expression.Block(typeof(Quaternion), new linq.ParameterExpression[] { temp }, assign, call, temp);
      }
    };
    /// <summary>
    /// Return this quaternion's conjugate.
    /// </summary>
    public QuaternionBl Conjugate { get { return ConjugateOp.Make(this); } }

    /// <summary>
    /// The identity quaternion.
    /// </summary>
    public static readonly QuaternionBl Identity = Quaternion.Identity;

    public DegreeAngleBl Angle {
      get { return AngleOp.Make(this).Bl().ToDegrees(); }
    }
    public Point3DBl Axis {
      get { return AxisOp.Make(this); }
    }
    public BoolBl IsIdentity { get { return IsIdentityOp.Make(this); } }
    public BoolBl IsNormalized { get { return IsNormalizedOp.Make(this); } }
    /*
    public QuaternionBl SLerp(QuaternionBl to, DoubleBl t) {
      return SlerpOp.Make(this, to, t);
    }*/
    static QuaternionBl() {
      Register(v => v);
      Plus.Apply = (q0, q1) => q0 + q1;
      Minus.Apply = (q0, q1) => q0 - q1;
      Multiply.Apply = (q0, q1) => q0 * q1;
      EqualOp.Apply = (q0, q1) => q0 == q1;
      NotEqualOp.Apply = (q0, q1) => q0 != q1;
    }
  }

  public static partial class D3DExtensions {
    public static QuaternionBl Bl(this Expr<Quaternion> v) { return v; }
    public static QuaternionRotation3DBl Bl(this Expr<QuaternionRotation3D> v) { return v; }

    public static QuaternionBl Bl(this Quaternion v) { return v; }
    public static QuaternionRotation3DBl Bl(this QuaternionRotation3D v) { return v; }
  }
  /// <summary>
  /// Specifies the 3-D rotation to be used in a transformation.
  /// </summary>
  public abstract partial class BaseRotation3DBl<T, BRAND> : Brand<T, BRAND> where T : Rotation3D where BRAND : BaseRotation3DBl<T,BRAND> {
    public BaseRotation3DBl(Expr<T> v) : base(v) { }
    public static implicit operator Rotation3DBl(BaseRotation3DBl<T, BRAND> value) {
      return Rotation3DBl.UpCast<T>(value.Underlying);
    }
  }

  /// <summary>
  /// Specifies the 3-D rotation to be used in a transformation.
  /// </summary>
  public class Rotation3DBl : BaseRotation3DBl<Rotation3D, Rotation3DBl> {
    public Rotation3DBl(Expr<Rotation3D> Underlying) : base(Underlying) { }
    public static implicit operator Rotation3DBl(Expr<Rotation3D> target) { return new Rotation3DBl((target)); }
    public static implicit operator Rotation3DBl(Rotation3D target) { return (new Constant<Rotation3D>(target)); }
    static Rotation3DBl() { Register(v => v); }
    public new static Rotation3DBl UpCast<T>(Expr<T> value) where T : Rotation3D {
      return BaseRotation3DBl<Rotation3D, Rotation3DBl>.UpCast<T>(value);
    }
    public static readonly Rotation3DBl Identity = Rotation3D.Identity;
  }

  /// <summary>
  ///     Represents a 3-D rotation of a specified angle about a specified axis.
  /// </summary>
  public class AxisAngleRotation3DBl : BaseRotation3DBl<AxisAngleRotation3D, AxisAngleRotation3DBl> {
    public AxisAngleRotation3DBl(Expr<AxisAngleRotation3D> v) : base(v) { }

    public AxisAngleRotation3DBl() : this(new Constant<AxisAngleRotation3D>(new AxisAngleRotation3D())) { }
    public static implicit operator AxisAngleRotation3DBl(Expr<AxisAngleRotation3D> v) { return new AxisAngleRotation3DBl(v); }
    public static implicit operator AxisAngleRotation3DBl(AxisAngleRotation3D v) { return new Constant<AxisAngleRotation3D>(v); }
    static AxisAngleRotation3DBl() { Register(v => v); }
    /// <summary>
    ///     Gets or sets the angle of a 3-D rotation, in degrees. This is a dependency
    ///     property.
    /// </summary>
    public DegreeAngleBl Angle { 
      get { return Underlying.Property<double>(AxisAngleRotation3D.AngleProperty).Bl().ToDegrees(); }
      set { Angle.Bind = value; } 
    }
    /// <summary>
    ///     Gets or sets the axis of a 3-D rotation. This is a dependency property.
    /// </summary>
    public Point3DBl Axis {
      get { return Underlying.Property<Vector3D>(AxisAngleRotation3D.AxisProperty); }
      set { Axis.Bind = value; }
    }
  }

  /// <summary>
  /// Represents a rotation transformation defined as a quaternion.
  /// </summary>
  public class QuaternionRotation3DBl : BaseRotation3DBl<QuaternionRotation3D, QuaternionRotation3DBl> {
    public QuaternionRotation3DBl(Expr<QuaternionRotation3D> v) : base(v) { }
    public QuaternionRotation3DBl() : this(new Constant<QuaternionRotation3D>(new QuaternionRotation3D())) { }
    public static implicit operator QuaternionRotation3DBl(Expr<QuaternionRotation3D> v) { return new QuaternionRotation3DBl(v); }
    public static implicit operator QuaternionRotation3DBl(QuaternionRotation3D v) { return new Constant<QuaternionRotation3D>(v); }
    static QuaternionRotation3DBl() { Register(v => v); }
    /// <summary>
    ///  Gets or sets the System.Windows.Media.Media3D.Quaternion that defines the
    ///  destination rotation. This is a dependency property.
    /// </summary>
    public QuaternionBl Quaternion {
      get { return Underlying.Property<Quaternion>(QuaternionRotation3D.QuaternionProperty); }
      set { Quaternion.Bind = value; }
    }
  }


  public class PlaneratorBl : FrameworkElementBl<Planerator, PlaneratorBl> {
    public PlaneratorBl(Expr<Planerator> v) : base(v) { }
    public PlaneratorBl(CanvasBl Parent) : base(Parent, new Planerator()) { }
    public static implicit operator PlaneratorBl(Expr<Planerator> v) { return new PlaneratorBl(v); }
    public static implicit operator PlaneratorBl(Planerator v) { return new Constant<Planerator>(v); }

    public DegreePoint3DBl Rotation {
      get {
        return new DegreePoint3DBl(Planerator.RotationXProperty[this].Bl().ToDegrees(),
                                   Planerator.RotationYProperty[this].Bl().ToDegrees(),
                                   Planerator.RotationZProperty[this].Bl().ToDegrees());
      }
      set { Rotation.Bind = value; }
    }
    public DoubleBl FieldOfView {
      get { return Planerator.FieldOfViewProperty[this]; }
      set { FieldOfView.Bind = value; }
    }
    public Canvas Content { get { return CurrentValue.Content; } }
  }
  public class Planerator : FrameworkElement {
    internal static readonly GetProperty<Planerator, double> RotationXProperty = "RotationX".NewProperty<Planerator, double>(0);
    internal static readonly GetProperty<Planerator, double> RotationYProperty = "RotationY".NewProperty<Planerator, double>(0);
    internal static readonly GetProperty<Planerator, double> RotationZProperty = "RotationZ".NewProperty<Planerator, double>(0);
    internal static readonly GetProperty<Planerator, double> FieldOfViewProperty = 
      "FieldOfView".NewProperty<Planerator, double>(0, (self, oldV, newV) => self.Update3D(), (self,value) => value.Clamp(.5, 179.9));

    public readonly Canvas Content = new Canvas();

    private readonly QuaternionRotation3DBl _quaternionRotation;
    public Planerator() {
      _quaternionRotation = new QuaternionRotation3DBl() {
        Quaternion = (new QuaternionBl(_xAxis, Bl().Rotation.X)) *
                     (new QuaternionBl(_yAxis, Bl().Rotation.Y)) *
                     (new QuaternionBl(_zAxis, Bl().Rotation.Z)),

      };

    }
    public PlaneratorBl Bl() { return this; } 


    private void Update3D() {

    }
    private RotateTransform3D _rotationTransform = new RotateTransform3D();
    private Viewport3D _viewport3d;
    private ScaleTransform3D _scaleTransform = new ScaleTransform3D();

    static private readonly Point3D[] _mesh = new Point3D[] { new Point3D(0, 0, 0), new Point3D(0, 1, 0), new Point3D(1, 1, 0), new Point3D(1, 0, 0) };
    static private readonly Point[] _texCoords = new Point[] { new Point(0, 1), new Point(0, 0), new Point(1, 0), new Point(1, 1) };
    static private readonly int[] _indices = new int[] { 0, 2, 1, 0, 3, 2 };
    static private readonly Vector3D _xAxis = new Vector3D(1, 0, 0);
    static private readonly Vector3D _yAxis = new Vector3D(0, 1, 0);
    static private readonly Vector3D _zAxis = new Vector3D(0, 0, 1);

    private void SetCachingForObject(DependencyObject d) {
      RenderOptions.SetCachingHint(d, CachingHint.Cache);
      RenderOptions.SetCacheInvalidationThresholdMinimum(d, 0.5);
      RenderOptions.SetCacheInvalidationThresholdMaximum(d, 2.0);
    }
    private FrameworkElement CreateVisualChild() {
      MeshGeometry3D simpleQuad = new MeshGeometry3D() {
        Positions = new Point3DCollection(_mesh),
        TextureCoordinates = new PointCollection(_texCoords),
        TriangleIndices = new Int32Collection(_indices)
      };

      // Front material is interactive, back material is not.
      Material frontMaterial = new DiffuseMaterial(Brushes.White);
      frontMaterial.SetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty, true);

      VisualBrush vb = new VisualBrush(Content);
      SetCachingForObject(vb);  // big perf wins by caching!!
      Material backMaterial = new DiffuseMaterial(vb);

      _rotationTransform.Rotation = _quaternionRotation.CurrentValue;
      var xfGroup = new Transform3DGroup() { Children = { _scaleTransform, _rotationTransform } };

      GeometryModel3D backModel = new GeometryModel3D() { Geometry = simpleQuad, Transform = xfGroup, BackMaterial = backMaterial };
      Model3DGroup m3dGroup = new Model3DGroup() {
        Children = { new DirectionalLight(Colors.White, new Vector3D(0, 0, -1)), 
                                 new DirectionalLight(Colors.White, new Vector3D(0.1, -0.1, 1)),
                                 backModel }
      };

      // Non-interactive Visual3D consisting of the backside, and two lights.
      ModelVisual3D mv3d = new ModelVisual3D() { Content = m3dGroup };
      // Interactive frontside Visual3D
      Viewport2DVisual3D frontModel = new Viewport2DVisual3D() { Geometry = simpleQuad, Visual = Content, Material = frontMaterial, Transform = xfGroup };
      // Cache the brush in the VP2V3 by setting caching on it.  Big perf wins.
      SetCachingForObject(frontModel);
      // Scene consists of both the above Visual3D's.
      _viewport3d = new Viewport3D() { ClipToBounds = false, Children = { mv3d, frontModel } };

      return _viewport3d;
    }
  }
}